package com.cskaoyan.market.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 小焦
 * @since 2022/10/13 14:46
 */


public class ReflectUtils {
	private static  String SET_PREFIX="set";
	private static  String GET_PREFIX="get";

	public static <T, E> List<E> copyProperties(List<T> source, Class<E> tClass) {

		// 判断传入源数据是否为空，如果空，则抛自定义异常
		if (null == source) {
			throw new RuntimeException("数据源为空");
		}

		// 创建一个集合，用于存储目标对象，全部数据抓换完成后，将该集合返回
		List<E> targetList = new ArrayList<>();


		// 循环取到单个源对象E
		for (T t : source) {
			// 获取源对象的类的详情信息
			Class<?> sClass = t.getClass();
			// 获取源对象的所有属性
			Field[] sFields = sClass.getDeclaredFields();
			// 获取目标对象的所有属性
			Field[] tFields = tClass.getDeclaredFields();

			E target;
			try {
				// 通过类的详情信息，创建目标对象 这一步等同于UserTwo target = new UserTwo()；
				target = tClass.newInstance();
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("目标对象创建失败");
			}

			// 循环取到源对象的单个属性
			for (Field sField : sFields) {
				// 循环取到目标对象的单个属性
				for (Field tField : tFields) {

					// 判断源对象的属性名、属性类型是否和目标对象的属性名、属性类型一致
					if (sField.getName().equals(tField.getName()) && sField.getGenericType().equals(tField.getGenericType())) {

						try {
							// 获取源对象的属性名，将属性名首字母大写，拼接如：getUsername、getId的字符串
							String sName = sField.getName();
							char[] sChars = sName.toCharArray();
							sChars[0] -= 32;
							String sMethodName = "get" + String.valueOf(sChars);
							// 获得属性的get方法
							Method sMethod = sClass.getMethod(sMethodName);
							// 调用get方法
							Object sFieldValue = sMethod.invoke(t);

							// 获取目标对象的属性名，将属性名首字母大写，拼接如：setUsername、setId的字符串
							String tName = tField.getName();
							char[] tChars = tName.toCharArray();
							tChars[0] -= 32;
							String tMethodName = "set" + String.valueOf(tChars);
							// 获得属性的set方法
							Method tMethod = tClass.getMethod(tMethodName, tField.getType());
							// 调用方法，并将源对象get方法返回值作为参数传入
							tMethod.invoke(target, sFieldValue);

							break;
						} catch (Exception e) {
							e.printStackTrace();
							throw new RuntimeException("转换失败，请检查属性类型是否匹配");
						}
					}
				}
			}
			// 将通过反射创建的目标对象放入集合中
			targetList.add(target);
		}
		// 返回集合
		return targetList;
	}


	public static <T,E> E copyObject(T t, Class<E> tClass) {

		// 判断传入源数据是否为空，如果空，则抛自定义异常
		if (null == t) {
			throw new RuntimeException("数据源为空");
		}


		// 获取源对象的类的详情信息
		Class<?> sClass = t.getClass();
		// 获取源对象的所有属性
		Field[] sFields = sClass.getDeclaredFields();
		// 获取目标对象的所有属性
		Field[] tFields = tClass.getDeclaredFields();

		E target;
		try {
			// 通过类的详情信息，创建目标对象 这一步等同于UserTwo target = new UserTwo()；
			target = tClass.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("目标对象创建失败");
		}

		// 循环取到源对象的单个属性
		for (Field sField : sFields) {
			// 循环取到目标对象的单个属性
			for (Field tField : tFields) {

				// 判断源对象的属性名、属性类型是否和目标对象的属性名、属性类型一致
				if (sField.getName().equals(tField.getName()) && sField.getGenericType().equals(tField.getGenericType())) {

					try {
						// 获取源对象的属性名，将属性名首字母大写，拼接如：getUsername、getId的字符串
						String sName = sField.getName();
						char[] sChars = sName.toCharArray();
						sChars[0] -= 32;
						String sMethodName = "get" + String.valueOf(sChars);
						// 获得属性的get方法
						Method sMethod = sClass.getMethod(sMethodName);
						// 调用get方法
						Object sFieldValue = sMethod.invoke(t);

						// 获取目标对象的属性名，将属性名首字母大写，拼接如：setUsername、setId的字符串
						String tName = tField.getName();
						char[] tChars = tName.toCharArray();
						tChars[0] -= 32;
						String tMethodName = "set" + String.valueOf(tChars);
						// 获得属性的set方法
						Method tMethod = tClass.getMethod(tMethodName, tField.getType());
						// 调用方法，并将源对象get方法返回值作为参数传入
						tMethod.invoke(target, sFieldValue);

						break;
					} catch (Exception e) {
						e.printStackTrace();
						throw new RuntimeException("转换失败，请检查属性类型是否匹配");
					}
				}
			}
		}

		// 返回集合
		return target;
	}





	/**
	 * 反射 获取当前类的 set方法 方法参数和方法名
	 * @param cls
	 * @return
	 * @throws ClassNotFoundException
	 */
	public static Map<String, Class<?>> getFieldAndType(Class<?> cls) throws ClassNotFoundException {

		HashMap<String, Class<?>> map = new HashMap<>();
		Field[] fields = cls.getDeclaredFields();
		for (Field field : fields) {
			String name = field.getName();
			// String s = name.toUpperCase();
			Class<?> type = field.getType();
			map.put(name, type);
		}
		return map;
	}




	/**
	 * 将当前字符串的首字母大写
	 * @param str
	 * @return
	 */
	public static String toUpperCaseFirstCode(String str) {
		String reg = "\\w{1,10}";
		if (!str.matches(str)) {
			throw new IllegalArgumentException("param is " + str);
		}
		char[] cs = str.toCharArray();
		cs[0] -= 32;
		return  String.valueOf(cs);
	}

}
